package com.zxjbyte.yiyi.framework.common.core.okhttp.retry;

import cn.hutool.extra.spring.SpringUtil;
import com.github.rholder.retry.AttemptTimeLimiter;
import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.SimpleTimeLimiter;
import com.google.common.util.concurrent.TimeLimiter;
import com.zxjbyte.yiyi.framework.common.constant.Constant;

import javax.annotation.Nonnull;
import javax.annotation.concurrent.Immutable;
import java.util.concurrent.*;

/**
 * 请求时间限制
 *
 * @Author zhangxingjia
 * @Date 2024/3/16 18:17
 * @Version: 1.0
 */
@Immutable
public class RequestAttemptTimeLimiter<V> implements AttemptTimeLimiter<V> {

    private static ExecutorService executorService = null;

    private final TimeLimiter timeLimiter;
    private final long duration;
    private final TimeUnit timeUnit;

    public static ExecutorService getExecutorService(){
        if(executorService == null){
            Executor executor = SpringUtil.getBean(Constant.DEFAULT_THREAD_POOL);
            executorService = (ExecutorService) executor;
        }
        return executorService;
    }

    public RequestAttemptTimeLimiter(long duration, @Nonnull TimeUnit timeUnit) {
        this(SimpleTimeLimiter.create(getExecutorService()), duration, timeUnit);
    }

    public RequestAttemptTimeLimiter(long duration, @Nonnull TimeUnit timeUnit, @Nonnull ExecutorService executorService) {
        this(SimpleTimeLimiter.create(executorService), duration, timeUnit);
    }

    private RequestAttemptTimeLimiter(@Nonnull TimeLimiter timeLimiter, long duration, @Nonnull TimeUnit timeUnit) {
        Preconditions.checkNotNull(timeLimiter);
        Preconditions.checkNotNull(timeUnit);
        this.timeLimiter = timeLimiter;
        this.duration = duration;
        this.timeUnit = timeUnit;
    }

    @Override
    public V call(Callable<V> callable) throws Exception {
        return timeLimiter.callWithTimeout(callable, duration, timeUnit);
    }
}
